package com.niiwoo.civet.mobile.controller.intelligenceInvest;


import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.google.common.collect.Lists;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.mobile.util.MaskUtil;
import com.niiwoo.civet.mobile.util.MoneyUtil;
import com.niiwoo.civet.mobile.vo.common.DeadlineVO;
import com.niiwoo.civet.mobile.vo.common.InvestingProjectVO;
import com.niiwoo.civet.mobile.vo.common.UserForbidVO;
import com.niiwoo.civet.mobile.vo.request.intelligenceInvest.*;
import com.niiwoo.civet.mobile.vo.request.invest.IntelligenceInvestConfirmRequestVO;
import com.niiwoo.civet.mobile.vo.response.intelligenceInvest.*;
import com.niiwoo.civet.mobile.vo.response.invest.IntelligenceInvestConfirmResponseVO;
import com.niiwoo.civet.mobile.vo.response.invest.InvestSettingPreconditionResponseVO;
import com.niiwoo.civet.trade.dto.common.DeadlineDTO;
import com.niiwoo.civet.trade.dto.common.InvestEvaluationDTO;
import com.niiwoo.civet.trade.dto.request.IntelligenceInvestDubboRequest;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceInvestCombinationRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceInvestDetailRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceInvestPageRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.SelectIntelligenceDeadlineRequestDTO;
import com.niiwoo.civet.trade.dto.response.IntelligenceInvestOrderResponseDTO;
import com.niiwoo.civet.trade.dto.response.InvestingProjectDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestDetailResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestSwitchResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.SelectIntelligenceDeadlineResponseDTO;
import com.niiwoo.civet.trade.enums.BorrowerTypeEnum;
import com.niiwoo.civet.trade.enums.Intelligence.IntelligenceSwitchSourceEnum;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.service.intelligenceInvest.IntelligenceInvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.civet.trade.service.project.NovicePorjectDubboService;
import com.niiwoo.civet.user.dto.response.ValidUserForbidResponseDTO;
import com.niiwoo.civet.user.enums.UserForbidTypeEnum;
import com.niiwoo.civet.user.service.UserForbidDubboService;
import com.niiwoo.tripod.base.enums.UserTypeEnum;
import com.niiwoo.tripod.base.utils.BigDecimals;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.component.AccessRateLimiter;
import com.niiwoo.tripod.web.shiro.UserAuthPrincipal;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Api(tags = "V5.5.5--智能投", description = "/intelligenceInvest")
@RestController
@RequestMapping("/intelligenceInvest/555")
@Slf4j
public class IntelligenceInvestController {

    @Reference(version = "1.0.0")
    private InvestDubboService investDubboService;
    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;
    @Reference(version = "1.0.0")
    private IntelligenceInvestDubboService intelligenceInvestDubboService;
    @Reference(version = "1.0.0")
    private UserForbidDubboService userForbidDubboService;
    @Reference(version = "1.0.0")
    private NovicePorjectDubboService novicePorjectDubboService;

    @Autowired
    private AccessRateLimiter accessRateLimiter;
    
    
    @ApiOperation("智能投开关(廖君君)")
    @AuthIgnore
    @PostMapping("/switch")
    public Result<IntelligenceInvestSwitchResponseVO> intelligenceInvestSwitch(@RequestBody IntelligenceInvestSwitchTypeRequestVO requestVO)  {
        IntelligenceInvestSwitchResponseVO responseVO = new IntelligenceInvestSwitchResponseVO();
        IntelligenceInvestSwitchResponseDTO responseDTO = intelligenceInvestDubboService.intelligenceInvestSwitch(requestVO.getSourceCode());
        responseVO.setIntelligenceInvestSwitch(responseDTO.getIntelligenceInvestSwitch().intValue());
        return Result.with(responseVO);
    }

    
    @ApiOperation("薪金宝智能投期限设定获取(刘春)")
    @AuthIgnore
    @PostMapping("/selectIntelligenceDeadline")
    public Result<SelectIntelligenceDeadlineResponseVO>  selectIntelligenceDeadline(@RequestBody SelectIntelligenceDeadlineRequestVO requestVO ){
    	SelectIntelligenceDeadlineRequestDTO requestDto = new SelectIntelligenceDeadlineRequestDTO();
    	requestDto.setChannelCode(requestVO.getPackageChannelCode());
    	SelectIntelligenceDeadlineResponseDTO queryResult =  intelligenceInvestDubboService.selectIntelligenceDeadline(requestDto);	
    	SelectIntelligenceDeadlineResponseVO result = new SelectIntelligenceDeadlineResponseVO();
    	if(Objects.isNull(queryResult)||CollectionUtils.isEmpty(queryResult.getSelector())) {
    		return Result.with(result);
    	}
    	List<DeadlineVO> deadlines = new ArrayList<>();
    	for (DeadlineDTO dto : queryResult.getSelector()) {
    		DeadlineVO vo = new DeadlineVO();
    		vo.setDeadline(dto.getDeadline());
    		vo.setDeadlineUnit(dto.getDeadlineUnit());
    		deadlines.add(vo);
		}
    	result.setSelector(deadlines);
    	// 可投资列表
    	List<DeadlineDTO> existSelector = queryResult.getExistSelector();
    	if(CollectionUtils.isEmpty(existSelector)) {
    		  return Result.with(result);
    	}
    	List<DeadlineVO> existDeadlines = new ArrayList<>();
    	for (DeadlineDTO deadlineDTO : existSelector) {
    		DeadlineVO vo = new DeadlineVO();
    		vo.setDeadline(deadlineDTO.getDeadline());
    		vo.setDeadlineUnit(deadlineDTO.getDeadlineUnit());
    		existDeadlines.add(vo);
		}
    	result.setExistSelector(existDeadlines);
    	
    	return Result.with(result);
    }
    
    @ApiOperation("薪金宝智能投详情(刘春)")
    @AuthIgnore
    @PostMapping("/getIntelligenceInvestDetailByDeadline")
    public Result<IntelligenceInvestDetailResponseVO> getIntelligenceInvestDetailByDeadLine(@RequestBody IntelligenceInvestDetailByDeadlineRequestVO requestVO){
    	 String userId = PrincipalContext.getUserId();
    	//参数验证
    	if(Objects.isNull(requestVO)||Objects.isNull(requestVO.getDeadline())||Objects.isNull(requestVO.getDeadline().getDeadline())||Objects.isNull(requestVO.getDeadline().getDeadlineUnit())||Objects.isNull(requestVO.getPackageChannelCode())) {
    		throw new BizException("TRD10004");
    	}
    	IntelligenceInvestPageRequestDTO intelligenceInvestPageRequestDTO = new IntelligenceInvestPageRequestDTO();
    	intelligenceInvestPageRequestDTO.setOffset(0);
    	intelligenceInvestPageRequestDTO.setPageSize(1);
    	intelligenceInvestPageRequestDTO.setUserId(userId);
    	intelligenceInvestPageRequestDTO.setPackageChannelCode(requestVO.getPackageChannelCode());
    	intelligenceInvestPageRequestDTO.setSourceCode(IntelligenceSwitchSourceEnum.SALARY.getCode());
    	DeadlineDTO deadlineDTO = new DeadlineDTO();
    	deadlineDTO.setDeadline(requestVO.getDeadline().getDeadline());
    	deadlineDTO.setDeadlineUnit(requestVO.getDeadline().getDeadlineUnit());
    	intelligenceInvestPageRequestDTO.setDeadline(deadlineDTO);
        PageResponseDTO<IntelligenceInvestResponseDTO> responsePageDTO = intelligenceInvestDubboService.getIntelligenceInvestList(intelligenceInvestPageRequestDTO);
    	
        if(CollectionUtils.isEmpty(responsePageDTO.getItems())) {
        	return Result.with(null);
        }
        Long packageId = responsePageDTO.getItems().get(0).getPackageId();
        //获取指定的智能投产品信息
    	 IntelligenceInvestDetailResponseVO responseVO = new IntelligenceInvestDetailResponseVO();
        
         IntelligenceInvestDetailRequestDTO dto = new IntelligenceInvestDetailRequestDTO();
         dto.setPackageId(packageId);
         dto.setUserId(userId);
         dto.setSourceCode(IntelligenceSwitchSourceEnum.SALARY.getCode());
         IntelligenceInvestDetailResponseDTO responseDTO = intelligenceInvestDubboService.getIntelligenceInvestDetail(dto);
         BeanUtils.copyProperties(responseDTO,responseVO);
         //智能投没有单独做为产品类型，和活动那边的类型对不上，红包id  智能投-10
         responseVO.setUserPrizeSuitProjectType(10);
         return Result.with(responseVO);
    }
    
    
    
    @ApiOperation("获取智能投列表(谢稳)")
    @AuthIgnore
    @PostMapping("/getIntelligenceInvestList")
    public Result<IntelligencePageResponseVO> getIntelligenceInvestList(@RequestBody IntelligenceInvestPageRequestVO requestVO) throws Exception {
        String userId = PrincipalContext.getUserId();
        if (userId != null) {
            boolean limit = accessRateLimiter.userLimit(userId, "intelligence_investList", 1, AccessRateLimiter.Unit.SECOND, 10);
            if (limit) {
                throw new BizException("SYS1001");  //亲爱的用户，您操作频率过快，请稍后再试
            }
        }
        IntelligencePageResponseVO responseVO = new IntelligencePageResponseVO();
        IntelligenceInvestPageRequestDTO requestDTO = new IntelligenceInvestPageRequestDTO();
        requestDTO.setOffset((requestVO.getPageNumber() - 1) * requestVO.getPageSize());
        requestDTO.setPageSize(requestVO.getPageSize());
        requestDTO.setUserId(userId);
        requestDTO.setPackageChannelCode(requestVO.getPackageChannelCode());
        requestDTO.setSourceCode(requestVO.getSourceCode());
        PageResponseDTO<IntelligenceInvestResponseDTO> responseDTO = intelligenceInvestDubboService.getIntelligenceInvestList(requestDTO);
        if(!CollectionUtils.isEmpty(responseDTO.getItems())){
            for (IntelligenceInvestResponseDTO investingProjectDTO : responseDTO.getItems()) {
                IntelligenceInvestResponseVO vo = this.convertToInvestingProjectVO(investingProjectDTO);
                responseVO.getItems().add(vo);
            }
            responseVO.setTotalCount(responseDTO.getTotalCount());
            responseVO.setTotalPage(responseDTO.getTotalPage());
        }
        return Result.with(responseVO);
    }

    private IntelligenceInvestResponseVO convertToInvestingProjectVO(IntelligenceInvestResponseDTO dto) {
        IntelligenceInvestResponseVO vo = new IntelligenceInvestResponseVO();
        vo.setTitle(dto.getTitle());
        vo.setBorrowRate(dto.getBorrowRate());
        vo.setBorrowRateDesc(BigDecimals.formatBorrowRate(dto.getBorrowRate()));
        vo.setDeadline(dto.getDeadline());
        vo.setDeadlineUnit(dto.getDeadlineUnit());
        vo.setInvestingAmount(dto.getInvestingAmount());
        vo.setProjectStatus(dto.getProjectStatus());
        vo.setRepaymentType(dto.getRepaymentType());
        vo.setPackageId(dto.getPackageId());
        vo.setPackageType(dto.getPackageType());
        vo.setContractAmount(dto.getContractAmount());
        if (Objects.nonNull(dto.getIncreaseInterest())) {
            IntelligenceInvestResponseVO.ActivityInfo activityInfo = new IntelligenceInvestResponseVO.ActivityInfo();
            activityInfo.setActivityTitle(dto.getActivityTitle());
            activityInfo.setIncreaseInterest(dto.getIncreaseInterest());
            vo.setActivityInfo(activityInfo);
        }
        return vo;
    }

    @ApiOperation("智能投详情(谢稳)")
    @AuthIgnore
    @PostMapping("/getIntelligenceInvestDetail")
    public Result<IntelligenceInvestDetailResponseVO> getIntelligenceInvestDetail(@RequestBody IntelligenceInvestDetailRequestVO requestVO) throws Exception {
        IntelligenceInvestDetailResponseVO responseVO = new IntelligenceInvestDetailResponseVO();
        String userId = PrincipalContext.getUserId();
        IntelligenceInvestDetailRequestDTO dto = new IntelligenceInvestDetailRequestDTO();
        dto.setPackageId(requestVO.getPackageId());
        dto.setUserId(userId);
        dto.setSourceCode(requestVO.getSourceCode());
        IntelligenceInvestDetailResponseDTO responseDTO = intelligenceInvestDubboService.getIntelligenceInvestDetail(dto);
        BeanUtils.copyProperties(responseDTO,responseVO);
        //智能投没有单独做为产品类型，和活动那边的类型对不上，红包id  智能投-10
        responseVO.setUserPrizeSuitProjectType(10);
        return Result.with(responseVO);
    }

    @ApiOperation("获取智能投组成标的(谢稳)")
    @AuthIgnore
    @PostMapping("/getIntelligenceInvestTotalProjectInfos")
    public Result<IntelligenceTotalProjectInfosResponseVO> getIntelligenceInvestTotalProjectInfos(@RequestBody IntelligenceInvestCombinationRequestVO requestVO) throws Exception {
        IntelligenceTotalProjectInfosResponseVO responseVO = new IntelligenceTotalProjectInfosResponseVO();
        IntelligenceInvestCombinationRequestDTO dto = new IntelligenceInvestCombinationRequestDTO();
        dto.setPackageId(requestVO.getPackageId());
        dto.setPageSize(requestVO.getPageSize());
        dto.setOffset((requestVO.getPageNumber() - 1) * requestVO.getPageSize());
        PageResponseDTO<InvestingProjectDTO> dtoPageResponseDTO = intelligenceInvestDubboService.getIntelligenceInvestTotalProjectInfos(dto);
        if(!CollectionUtils.isEmpty(dtoPageResponseDTO.getItems())){
            for (InvestingProjectDTO investingProjectDTO : dtoPageResponseDTO.getItems()) {
                InvestingProjectVO vo = this.convertToInvestingProjectVO(investingProjectDTO);
                responseVO.getItems().add(vo);
            }
            responseVO.setTotalPage(dtoPageResponseDTO.getTotalPage());
            responseVO.setTotalCount(dtoPageResponseDTO.getTotalCount());
        }
        return Result.with(responseVO);
    }
    @ApiOperation("智能投立即投资验证(刘春)")
    @PostMapping("/intelligenceInvestPreCondition")
    public Result<InvestSettingPreconditionResponseVO> intelligenceInvestPreCondition(@RequestBody IntelligenceInvestPreConditionRequestVO requestVO) throws InterruptedException, ExecutionException {
        //TODO liuchun 后续将对投资前置校验做封装
    	UserAuthPrincipal authPrincipal =  PrincipalContext.getUserPrincipal();
        String userId = authPrincipal.getUserId();
        InvestSettingPreconditionResponseVO responseVO = new InvestSettingPreconditionResponseVO();
        //投资账户信息
        AccountBaseResponse accountInfo = null;
        if(UserTypeEnum.ORGANIZATION.equals(authPrincipal.getUserType())) {
        	//指定机构账户
        	accountInfo = accountDubboService.getOrgAccount(userId, userId);
        }else {
        	accountInfo = accountDubboService.getNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        }
        if (accountInfo == null) {
            responseVO.setInvestorAccountStatus((byte) 0);
        } else {
            if (1 == accountInfo.getImportUserActiva()) {
                responseVO.setInvestorAccountStatus((byte) 2);
            } else {
                responseVO.setInvestorAccountStatus((byte) 1);
            }
            responseVO.setAmount(accountInfo.getAvailableAmount());
            responseVO.setNonePwdInvestStatus(accountInfo.getTender());
        }
        //风险测评信息
        Future<InvestEvaluationDTO> evaluationFuture = RpcContext.getContext().asyncCall(() -> investDubboService.getInvestEvaluationInfo(userId));
        Future<ValidUserForbidResponseDTO> forbidFuture = RpcContext.getContext().asyncCall(() -> userForbidDubboService.queryValidUserForbidInfo(userId, UserForbidTypeEnum.INVESTOR));
        InvestEvaluationDTO evaluationDTO = evaluationFuture.get();
        responseVO.setHadEvaluate(evaluationDTO.getHadEvaluate());
        responseVO.setEvaluateLevel(evaluationDTO.getLevel());
        responseVO.setSurplusCanInvestAmount(evaluationDTO.getSurplusCanInvestAmount());
        ValidUserForbidResponseDTO forbidInfo = forbidFuture.get();
        //投资相关行为限制
        if (forbidInfo != null) {
            UserForbidVO forbidVO = new UserForbidVO(forbidInfo.getForbidType(), forbidInfo.getForbidTypeName(), forbidInfo.getForbidDesc());
            responseVO.setUserForbidList(Lists.newArrayList(forbidVO));
        }
        return Result.with(responseVO);
    }
    @ApiOperation("智能投投资确认(刘春)")
    @PostMapping("/intelligenceInvestConfirm")
    public Result<IntelligenceInvestConfirmResponseVO> intelligenceInvestConfirm(@RequestBody IntelligenceInvestConfirmRequestVO confirmRequestVO) {
        UserAuthPrincipal authPrincipal =  PrincipalContext.getUserPrincipal();
        IntelligenceInvestDubboRequest request  = new IntelligenceInvestDubboRequest();
        //参数封装
        request.setUserId(authPrincipal.getUserId());
        request.setInvestAmount(MoneyUtil.scale2HalfUp(confirmRequestVO.getAmount()));//精度处理
        request.setProjectPackageId(confirmRequestVO.getProjectPackageId());
        request.setPrizeId(confirmRequestVO.getPrizeId());
        UserTypeEnum userType = authPrincipal.getUserType();
        request.setInvestUserType(Objects.isNull(userType)?UserTypeEnum.PERSONAL.getValue():userType.getValue());
        //智能投
        IntelligenceInvestOrderResponseDTO investOrderResponseDTO = intelligenceInvestDubboService.intelligenceInvest(request);

        IntelligenceInvestConfirmResponseVO responseVO = new IntelligenceInvestConfirmResponseVO();
        responseVO.setAmount(request.getInvestAmount());
        responseVO.setInterest(investOrderResponseDTO.getInterest());
        responseVO.setProjectPackageInvestOrder(responseVO.getProjectPackageInvestOrder());
        return Result.with(responseVO);
    }
    /**
     * 可投标的列表DTO转VO
     *
     * @param dto
     * @return
     */
    private InvestingProjectVO convertToInvestingProjectVO(InvestingProjectDTO dto) {
        InvestingProjectVO vo = new InvestingProjectVO();
        vo.setProjectId(dto.getProjectId());
        vo.setProjectType(dto.getProjectType());
        vo.setUserPrizeSuitProjectType(ProjectTypeEnum.getEnum(dto.getProjectType()).getUserPrizeSuitProjectType());
        vo.setBorrowerUserId(dto.getBorrowerUserId());
        if (BorrowerTypeEnum.COMPANY.getType().equals(dto.getBorrowerType())) {
            vo.setBorrowerNickName(MaskUtil.maskCompanyName(dto.getBorrowerNickName()));
        } else {
            vo.setBorrowerNickName(dto.getBorrowerNickName());
        }
        vo.setBorrowerHeadImage(dto.getBorrowerHeadImage());
        vo.setLoanType(dto.getLoanType());
        vo.setLoanTypeDesc(dto.getLoanTypeDesc());
        vo.setIsMasterBorrower(dto.getIsMasterBorrower());
        vo.setBorrowerGender(dto.getBorrowerGender());
        vo.setBorrowerNiiwooScore(dto.getBorrowerNiiwooScore());
        vo.setLoanTimes(dto.getLoanTimes());
        vo.setCity(dto.getCity());
        vo.setArea(dto.getArea());
        vo.setPublishTime(dto.getPublishTime());
        vo.setTitle(dto.getTitle());
        vo.setBorrowRate(dto.getBorrowRate());
        vo.setBorrowRateDesc(BigDecimals.formatBorrowRate(dto.getBorrowRate()));
        vo.setDeadline(dto.getDeadline());
        vo.setDeadlineUnit(dto.getDeadlineUnit());
        vo.setContractAmount(dto.getContractAmount());
        vo.setInvestingAmount(dto.getInvestingAmount());
        vo.setProjectStatus(dto.getProjectStatus());
        vo.setCreditType(dto.getCreditType());
        vo.setBorrowerType(dto.getBorrowerType());
        vo.setRepaymentType(dto.getRepaymentType());
        vo.setBaseInvestMoney(dto.getBaseInvestMoney());
        if (Objects.nonNull(dto.getInterestAddRate())) {
            InvestingProjectVO.ActivityInfo activityInfo = new InvestingProjectVO.ActivityInfo();
            activityInfo.setIncreaseInterest(dto.getInterestAddRate());
            activityInfo.setActivityTitle(dto.getInterestAddTitle());
            vo.setActivityInfo(activityInfo);
        }
        return vo;
    }
}
